package com.zjuee.web.basic.captcha.utils;




import org.apache.commons.lang3.RandomUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * 验证码生成器
 *
 * @author wu liang
 * @since 1.0
 */
public class ValidateCode {
    // 图片的宽度。  
    private int width = 120;
    // 图片的高度。  
    private int height = 40;
    // 验证码字符个数  
    private int codeCount = 4;
    // 验证码干扰线数  
    private int lineCount = 50;
    // 验证码  
    private String code = null;
    // 验证码图片Buffer  
    private BufferedImage buffImg = null;

    private char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
            'I', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
            'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9' };


    // 生成随机数  
    private Random random = new Random();

    public ValidateCode() {
        this.createCode();
    }
    public ValidateCode(int width, int height) {
        this.width = width;
        this.height = height;
        this.createCode();
    }

    /**
     * @param width     图片宽
     * @param height    图片高
     * @param codeCount 字符个数
     * @param lineCount 干扰线条数
     */
    public ValidateCode(int width, int height, int codeCount, int lineCount) {
        this.width = width;
        this.height = height;
        this.codeCount = codeCount;
        this.lineCount = lineCount;
        this.createCode();
    }

    private void createCode() {
        /**
         * 每个字符的宽度
         */
        int codeX = width / (codeCount);
        // 左右边距 半个字符
        int marginX = codeX / 2;
        // 为了好看 我们需要字体要稍微紧凑 此变量表示每个字体左边距的偏移量，可能小于字体的实际宽度 造成重叠
        int offsetX = (width - codeX) / codeCount;
        /**
         * 图像buffer
         */
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = buffImg.createGraphics();

        /**
         * 将图像填充为白色
         */
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);

        /**
         *  创建字体
         */
        g.setFont(FontUtil.getFont_EN(Font.BOLD, height - 5));

        /**
         * 绘制干扰线
         */
        for (int i = 0; i < lineCount; i++) {
            int x1 = getRandomNumber(width);
            int y1 = getRandomNumber(height);
            int x2 = x1 + getRandomNumber(width / 5);
            int y2 = y1 + getRandomNumber(height / 5);
            g.setColor(getRandomColor());
            g.drawLine(x1, y1, x2, y2);
        }

        /**
         *  随机产生验证码字符
         */
        StringBuilder randomCode = new StringBuilder();
        for (int i = 0; i < codeCount; i++) {
            // 第一个数字不能是0
            int randomIndex;
            if (i == 0)
                randomIndex = RandomUtils.nextInt(1, codeSequence.length);
            else
                randomIndex = random.nextInt(codeSequence.length);
            String strRand = String.valueOf(codeSequence[randomIndex]);

            // 设置字体颜色
            g.setColor(getRandomColor());
            //设置字体位置
            g.drawString(strRand, marginX + i * offsetX, getRandomNumber(height - codeX) + codeX);
            randomCode.append(strRand);
        }
        code = randomCode.toString();
    }

    /**
     * 获取随机颜色
     */
    private Color getRandomColor() {
        int r = getRandomNumber(190);
        int g = getRandomNumber(190);
        int b = getRandomNumber(190);
        return new Color(r, g, b);
    }

    /**
     * 获取随机数
     */
    private int getRandomNumber(int number) {
        return random.nextInt(number);
    }

    public void write(String path) throws IOException {
        OutputStream sos = new FileOutputStream(path);
        this.write(sos);
    }

    public void write(OutputStream sos) throws IOException {
        ImageIO.write(buffImg, "png", sos);
        sos.close();
    }

    public BufferedImage getBuffImg() {
        return buffImg;
    }

    public String getCode() {
        return code;
    }
}